#include <gtest/gtest.h>
#include "Poller/PipeWrap.h"
#include <thread>
#include <chrono>

using namespace toolkit;
using namespace std;

class PipeWrapTest : public testing::Test {
protected:
    PipeWrap pipe;
};

TEST_F(PipeWrapTest, BasicCreation) {
    EXPECT_NE(pipe.readFD(), -1);
    EXPECT_NE(pipe.writeFD(), -1);
    EXPECT_NE(pipe.readFD(), pipe.writeFD());
}

TEST_F(PipeWrapTest, SimpleWriteRead) {
    const char* test_data = "Hello Pipe";
    int len = strlen(test_data);
    
    // 写入数据
    int written = pipe.write(test_data, len);
    EXPECT_EQ(written, len);
    
    // 读取数据
    char buffer[256] = {0};
    int read = pipe.read(buffer, sizeof(buffer));
    EXPECT_EQ(read, len);
    EXPECT_STREQ(buffer, test_data);
}

TEST_F(PipeWrapTest, LargeDataTransfer) {
    const int data_size = 4096 * 10; // 1MB
    vector<char> test_data(data_size, 'A');
    
    // 分块写入
    const int chunk_size = 4096;
    for (int i = 0; i < data_size; i += chunk_size) {
        int size = min(chunk_size, data_size - i);
        int written = pipe.write(test_data.data() + i, size);
        EXPECT_EQ(written, size);
    }
    
    // 分块读取验证
    vector<char> buffer(data_size);
    for (int i = 0; i < data_size; i += chunk_size) {
        int size = min(chunk_size, data_size - i);
        int read = pipe.read(buffer.data() + i, size);
        EXPECT_EQ(read, size);
    }
    EXPECT_EQ(memcmp(test_data.data(), buffer.data(), data_size), 0);
}

TEST_F(PipeWrapTest, ReopenTest) {
    int old_read_fd = pipe.readFD();
    int old_write_fd = pipe.writeFD();
    
    pipe.reOpen();
    
    EXPECT_NE(pipe.readFD(), -1);
    EXPECT_NE(pipe.writeFD(), -1);
    EXPECT_NE(pipe.readFD(), old_read_fd);
    EXPECT_NE(pipe.writeFD(), old_write_fd);
}

TEST_F(PipeWrapTest, NonBlockingRead) {
    char buffer[256];
    int read = pipe.read(buffer, sizeof(buffer));
    EXPECT_EQ(read, -1); // 非阻塞模式下没有数据可读应返回-1
}

TEST_F(PipeWrapTest, ThreadCommunication) {
    const char* test_data = "Thread message";
    int len = strlen(test_data);
    
    thread writer([this, test_data, len]() {
        this_thread::sleep_for(chrono::milliseconds(100));
        int written = pipe.write(test_data, len);
        EXPECT_EQ(written, len);
    });
    
    char buffer[256] = {0};
    int read = pipe.read(buffer, sizeof(buffer));
    writer.join();
    
    EXPECT_EQ(read, len);
    EXPECT_STREQ(buffer, test_data);
}